namespace SimpleWebServices.Configuration
{
    using System;
    using System.Collections.ObjectModel;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using SimpleWebServices;
    using Xunit;

    public sealed class FileSettingCollectionFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<FileSettingCollection>()
                .DerivesFrom<Collection<FileSetting>>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .XmlRoot("files")
                .Implements<IXmlSerializable>()
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            FileSettingCollection actual = (
                "<files>" +
                    "<file content-type='text/css' path='/example.css' />" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.Equal<int>(2, actual.Count);

            Assert.Equal<string>("text/css", actual[0].ContentType);
            Assert.Equal<string>("/example.css", actual[0].Path);

            Assert.Equal<string>("text/plain", actual[1].ContentType);
            Assert.Equal<string>("/example.txt", actual[1].Path);
        }

        [Fact]
        public void deserialize_whenGrouped()
        {
            FileSettingCollection actual = (
                "<files>" +
                    "<css content-type='text/css' cache-control='public' cache-condition='expires' duration='P1D'>" +
                        "<file path='/example.css' />" +
                    "</css>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.Equal<int>(2, actual.Count);

            Assert.Equal<string>("expires", actual[0].CacheCondition);
            Assert.Equal<string>("public", actual[0].CacheControl);
            Assert.Equal<string>("text/css", actual[0].ContentType);
            Assert.Equal<string>("P1D", actual[0].DurationValue);
            Assert.Equal<string>("/example.css", actual[0].Path);

            Assert.Null(actual[1].CacheCondition);
            Assert.Null(actual[1].CacheControl);
            Assert.Equal<string>("text/plain", actual[1].ContentType);
            Assert.Equal<string>("/example.txt", actual[1].Path);
        }

        [Fact]
        public void deserializeEmpty()
        {
            FileSettingCollection actual = "<files />".Deserialize<FileSettingCollection>();

            Assert.Empty(actual);
        }

        [Fact]
        public void serialize()
        {
            FileSettingCollection obj = new FileSettingCollection();
            obj.Add("<file content-type='text/plain' path='/example.txt' />".Deserialize<FileSetting>());
            obj.Add("<file content-type='text/css' path='/example.css' />".Deserialize<FileSetting>());

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate("2=count(/files/file)"));

            Assert.True((bool)navigator.Evaluate("1=count(/files/file[@content-type='text/plain'][@path='/example.txt'])"));
            Assert.True((bool)navigator.Evaluate("1=count(/files/file[@content-type='text/css'][@path='/example.css'])"));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new FileSettingCollection());
        }

        [Fact]
        public void prop_Indexer_string()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.NotNull(obj["/example.txt"]);
        }

        [Fact]
        public void prop_Indexer_stringCaseInsentive()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.NotNull(obj["/Example.TXT"]);
        }

        [Fact]
        public void prop_Indexer_stringNotFound()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.Null(obj["/example.css"]);
        }

        [Fact]
        public void prop_Indexer_stringEmpty()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.Null(obj[string.Empty]);
        }

        [Fact]
        public void prop_Indexer_stringNull()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.Null(obj[null as string]);
        }

        [Fact]
        public void op_Contains_string()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.True(obj.Contains("/example.txt"));
        }

        [Fact]
        public void op_Contains_stringCaseInsentive()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.True(obj.Contains("/Example.TXT"));
        }

        [Fact]
        public void op_Contains_stringNotFound()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='/example.txt' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.False(obj.Contains("/example.css"));
        }

        [Fact]
        public void op_Contains_stringEmpty()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' path='' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.False(obj.Contains(string.Empty));
        }

        [Fact]
        public void op_Contains_stringNull()
        {
            FileSettingCollection obj = (
                "<files>" +
                    "<file content-type='text/plain' />" +
                "</files>").Deserialize<FileSettingCollection>();

            Assert.False(obj.Contains(null as string));
        }

        [Fact]
        public void IXmlSerializable_op_GetSchema()
        {
            Assert.Throws<NotSupportedException>(() => (new FileSettingCollection() as IXmlSerializable).GetSchema());
        }

        [Fact]
        public void IXmlSerializable_op_ReadXml_XmlReaderNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new FileSettingCollection() as IXmlSerializable).ReadXml(null as XmlReader));
        }

        [Fact]
        public void IXmlSerializable_op_WriteXml_XmlWriterNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new FileSettingCollection() as IXmlSerializable).WriteXml(null as XmlWriter));
        }
    }
}